﻿using System;
using System.Collections.Generic;
using System.Text;

namespace OkTool.Util
{
    /// <summary>
    /// 委托
    /// </summary>
    public class DelegateV2Util
    {

        /// <summary>
        /// 带返回值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <returns></returns>
        public delegate string EventDelegateString<T>(T e) where T : EventArgs;

        /// <summary>
        /// 无返回值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        public delegate void EventDelegateVoid<T>(T e) where T : EventArgs;


        public static readonly DelegateV2Util Instance = new DelegateV2Util();
        private readonly Dictionary<Type, Delegate> _delegates = new Dictionary<Type, Delegate>();



        private DelegateV2Util()
        {
        }
        /// <summary>
        /// 添加委托(无返回值)
        /// <para> DelegateV2Util.Instance.AddVoid&lt;<paramref name="LogEntity"/>&gt;(DoLog)</para>
        /// <para>LogEntity继承EventArgs</para>
        /// <para>DoLog是方法</para>
        /// <para>void DoLog(LogEntity resultEntity)</para>
        /// </summary>
        /// <typeparam name="T">实体泛型,约束EventArgs</typeparam>
        /// <param name="listener"></param>
        public void AddVoid<T>(EventDelegateVoid<T> listener) where T : EventArgs
        {
            Delegate a;
            if (this._delegates.TryGetValue(typeof(T), out a))
            {
                this._delegates[typeof(T)] = Delegate.Combine(a, listener);
            }
            else
            {
                this._delegates[typeof(T)] = listener;
            }
        }

        /// <summary>
        /// 添加委托(有回值)
        /// <para> DelegateV2Util.Instance.Add&lt;<paramref name="LogEntity"/>&gt;(DoLog)</para>
        /// <para>LogEntity继承EventArgs</para>
        /// <para>DoLog是方法</para>
        /// <para>void DoLog(LogEntity resultEntity)</para>
        /// </summary>
        /// <typeparam name="T">实体泛型,约束EventArgs</typeparam>
        /// <param name="listener"></param>
        public void Add<T>(EventDelegateString<T> listener) where T : EventArgs
        {
            Delegate a;
            if (this._delegates.TryGetValue(typeof(T), out a))
            {
                this._delegates[typeof(T)] = Delegate.Combine(a, listener);
            }
            else
            {
                this._delegates[typeof(T)] = listener;
            }
        }


        /// <summary>
        /// 回调(无返回值)
        /// <para> DelegateV2Util.Instance.InvokeVoid(new LogEntity())</para>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        public void InvokeVoid<T>(T e) where T : EventArgs
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }
            Delegate @delegate;
            if (this._delegates.TryGetValue(typeof(T), out @delegate))
            {
                EventDelegateVoid<T> eventDelegate = @delegate as EventDelegateVoid<T>;
                if (eventDelegate != null)
                {
                    eventDelegate(e);
                }
            }
        }


        /// <summary>
        /// 回调(有返回值)
        /// <para> var res=DelegateV2Util.Instance.Invoke(new LogEntity())</para>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <returns></returns>
        public string Invoke<T>(T e) where T : EventArgs
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }
            Delegate @delegate;
            if (this._delegates.TryGetValue(typeof(T), out @delegate))
            {
                EventDelegateString<T> eventDelegate = @delegate as EventDelegateString<T>;
                if (eventDelegate != null)
                {
                    return eventDelegate.Invoke(e);
                }
            }

            return "";
        }

        /// <summary>
        /// 删除委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listener"></param>
        public void RemoveVoid<T>(EventDelegateVoid<T> listener) where T : EventArgs
        {
            Delegate source;
            if (this._delegates.TryGetValue(typeof(T), out source))
            {
                Delegate @delegate = Delegate.Remove(source, listener);
                if (@delegate == null)
                {
                    this._delegates.Remove(typeof(T));
                }
                else
                {
                    this._delegates[typeof(T)] = @delegate;
                }
            }
        }


        /// <summary>
        /// 删除委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listener"></param>
        public void Remove<T>(EventDelegateString<T> listener) where T : EventArgs
        {
            Delegate source;
            if (this._delegates.TryGetValue(typeof(T), out source))
            {
                Delegate @delegate = Delegate.Remove(source, listener);
                if (@delegate == null)
                {
                    this._delegates.Remove(typeof(T));
                }
                else
                {
                    this._delegates[typeof(T)] = @delegate;
                }
            }
        }
      



    }
}
